// Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
//
// Licensed under the Mulan PSL v2.
// You can use this file according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of the License at
//
//     http://license.coscl.org.cn/MulanPSL2
//
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
// FOR MORE DETAILS.

#include "DBManager/Database/DatabaseFactory.h"

#include <map>
#include <string>

#include "DBManager/Database/HDF5Database.h"
#include "DBManager/Database/IDatabase.h"

#include "DatabaseFactory.h"

using namespace SG::DBManager;

class SG::DBManager::DatabaseFactoryPrivate
{
  public:
    ~DatabaseFactoryPrivate ();

    // 构造函数
    DatabaseFactoryPrivate () = default;

    // 拷贝构造函数
    DatabaseFactoryPrivate (const DatabaseFactoryPrivate& other) = delete;

    // 拷贝赋值运算符
    DatabaseFactoryPrivate& operator= (const DatabaseFactoryPrivate& other) = delete;

    // 移动构造函数
    DatabaseFactoryPrivate (DatabaseFactoryPrivate&& other) noexcept = delete;

    // 移动赋值运算符
    DatabaseFactoryPrivate& operator= (DatabaseFactoryPrivate&& other) noexcept = delete;

    std::map<SG::DBManager::DatabaseFactory::DatabaseType, std::map<std::string, IDatabase*>>& GetDatabases ()
    {
        return m_Databases;
    }
    void SetDatabases (const std::map<SG::DBManager::DatabaseFactory::DatabaseType, std::map<std::string, IDatabase*>>& Databases)
    {
        m_Databases = Databases;
    }

  private:
    std::map<SG::DBManager::DatabaseFactory::DatabaseType, std::map<std::string, IDatabase*>> m_Databases;
};

SG::DBManager::DatabaseFactoryPrivate::~DatabaseFactoryPrivate ()
{
    for (auto&& dmap : m_Databases)
    {
        for (auto&& db : dmap.second)
        {
            delete db.second;
        }
    }
}

DatabaseFactory::DatabaseFactory ()
{
    m_dataBaseFactoryPrivate = new DatabaseFactoryPrivate ();
}

DatabaseFactory::~DatabaseFactory ()
{
    delete m_dataBaseFactoryPrivate;
}

/**
 * @brief 创建指定类型的数据库实例并存储在全局 map 中。
 *
 * @param dataType 要创建的数据库类型（如 memory 或 HDF5）。
 * @param folderPath 数据库文件所在的文件夹路径。
 * @param fileName 数据库文件名。
 */
void DatabaseFactory::CreatDatabase (DatabaseType dataType, const std::string& folderPath, const std::string& fileName)
{
    std::string const fullPath = folderPath + "/" + fileName;

    switch (dataType)
    {
    case DatabaseFactory::MEMORY:
        // 未来扩展内存数据库创建逻辑
        break;
    case DatabaseFactory::HDF5:
        m_dataBaseFactoryPrivate->GetDatabases ()[dataType][fullPath] = new HDF5Database (folderPath, fileName);
        break;
    default:
        break;
    }
}

void DatabaseFactory::DestroyDatabase (IDatabase* database)
{
    m_dataBaseFactoryPrivate->GetDatabases ().erase (( DatabaseType ) database->GetDatabaseType ());
    delete database;
}

/**
 * @brief 获取指定类型的数据库实例，如果不存在则创建。
 *
 * @param dataType 数据库类型。
 * @param folderPath 数据库文件所在的文件夹路径。
 * @param fileName 数据库文件名。
 * @return 返回指向指定数据库实例的共享指针。
 */
IDatabase* DatabaseFactory::GetDatabase (DatabaseType dataType, const std::string& folderPath, const std::string& fileName)
{
    std::string const fullPath = folderPath + "/" + fileName;
    auto              iter     = m_dataBaseFactoryPrivate->GetDatabases ().find (dataType);

    if (iter == m_dataBaseFactoryPrivate->GetDatabases ().end ())
    {
        CreatDatabase (dataType, folderPath, fileName);
    }
    else
    {
        auto iterFullPath = m_dataBaseFactoryPrivate->GetDatabases ()[dataType].find (fullPath);
        if (iterFullPath == m_dataBaseFactoryPrivate->GetDatabases ()[dataType].end ())
        {
            CreatDatabase (dataType, folderPath, fileName);
        }
    }

    return m_dataBaseFactoryPrivate->GetDatabases ()[dataType][fullPath];
}
